package edu.njust.httpmanager.controller;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.fasterxml.jackson.databind.ObjectMapper;
import edu.njust.httpmanager.annotation.AuthCheck;
import edu.njust.httpmanager.common.Result;
import edu.njust.httpmanager.common.UserContext;
import edu.njust.httpmanager.constance.ResponseCode;
import edu.njust.httpmanager.constance.UserAuth;
import edu.njust.httpmanager.entity.ProgramMember;
import edu.njust.httpmanager.entity.dto.ProgramMemberDto;
import edu.njust.httpmanager.exception.CustomException;
import edu.njust.httpmanager.service.IProgramMemberService;
import edu.njust.httpmanager.utils.JwtUtil;
import io.jsonwebtoken.Claims;
import jakarta.annotation.Resource;
import org.apache.commons.lang3.StringUtils;
import org.springframework.web.bind.annotation.*;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
public class ProgramMemberController {

    @Resource
    private IProgramMemberService memberService;

    /**
     * 生成邀请token
     * @param programId 项目ID
     * @param auth 被邀请者权限
     */
    @AuthCheck(UserAuth.ADMIN)
    @GetMapping("/invite/{programId}")
    public Result<String> generateLink(@PathVariable Long programId, String auth) {

        if (auth == null || !StringUtils.containsAny(auth, new String[]{UserAuth.EDITOR, UserAuth.READ, UserAuth.ADMIN})) {
            throw new CustomException(ResponseCode.PARAMS_ERROR);
        }

        ProgramMember member = new ProgramMember();
        member.setUserRole(auth);
        member.setProgramId(programId);

        // 生成Token （存储了用户ID）
        Map<String, Object> claims = new HashMap<>();
        claims.put("member", member);
        String link = JwtUtil.create(claims, 1);

        return Result.success(link);
    }

    /**
     * 获取项目的所有成员
     */
    @GetMapping("/member/{programId}")
    public Result<List<ProgramMemberDto>> getMembers(@PathVariable Long programId) {
        // 返回的结果
        List<ProgramMemberDto> members;

        members = memberService.getWithAuthAndNameByProgramId(programId);

        return Result.success(members);
    }

    /**
     * 删除项目成员
     */
    @AuthCheck(UserAuth.ADMIN)
    @DeleteMapping("/member/{programId}")
    public Result<Void> deleteFromMember(@PathVariable Long programId, String userId) {

        Long id = UserContext.getUser().getId();

        if (StringUtils.isAnyBlank(userId)) {
            throw new CustomException(ResponseCode.PARAMS_ERROR);
        }

        if (id.compareTo(Long.parseLong(userId)) == 0) {
            throw new CustomException("不可以对自己进行操作");
        }

        LambdaQueryWrapper<ProgramMember> memberLambdaQueryWrapper = new LambdaQueryWrapper<>();
        memberLambdaQueryWrapper.eq(ProgramMember::getProgramId, userId);

        boolean remove = memberService.remove(memberLambdaQueryWrapper);
        if (!remove) {
            return Result.error(ResponseCode.SYSTEM_ERROR);
        }

        return Result.success();
    }

    @AuthCheck(UserAuth.ADMIN)
    @PutMapping("/member/{programId}")
    public Result<Void> updateAuth (@PathVariable Long programId, @RequestBody ProgramMember programMember) {

        if (programMember.getUserId().equals(UserContext.getUser().getId())) {
            throw new CustomException("不可以对自己进行操作");
        }

        memberService.updateById(programMember);

        return Result.success();
    }
    /**
     * 用户加入项目
     */
    @PostMapping("/join")
    public Result<Void> join(@RequestBody Map<String, String> map) {

        String token = map.get("token");

        if (!JwtUtil.validateJwtToken(token)) {
            throw new CustomException("邀请链接已经失效");
        }

        ObjectMapper objectMapper = new ObjectMapper();
        // 解析token
        Claims claims = JwtUtil.getClaimsFromJwtToken(token);
        ProgramMember member = objectMapper.convertValue(claims.get("member"), ProgramMember.class);

        Long userId = UserContext.getUser().getId();
        member.setUserId(userId);

        if (!memberService.joinIn(member)) {
            return Result.error(ResponseCode.SYSTEM_ERROR);
        }

        return Result.success();
    }
}
